簡介
在Windows、OS/2、以及其他的一些作業系統(帶有第三方的開發工具)上,動態數據交換(Dynamic Data Exchange,DDE)允許數據在程式間被共享或者通信。例如,當你在你的資料庫程式中改變一個表,或者電子製表軟體中的數據項時,則這個表或者數據項也需要在你可能使用的其他軟體中進行相應的改變。DDE是使用共享記憶體作為公共交換區域並提供應用程式一個協定或者命令集以及訊息格式的進程間通信。DDE使用了客戶端/伺服器模型,在這個模型中,應用程式對數據的請求在客戶端進行處理,同時應用程式對數據的提供在伺服器端處理。
工作原理
DDE的工作原理是:
兩個同時運行的程式間通過DDE方式交換數據時是客戶/伺服器關係,一旦客戶和伺服器建立起來連線關係,則當伺服器中的數據發生變化後就會馬上通知客戶。通過DDE方式建立的數據連線通道是雙向的,即客戶不但能夠讀取伺服器中的數據,而且可以對其進行修改。
DDE和剪貼簿一樣既支持標準數據格式(如文本、點陣圖等),又可以支持自定義的數據格式。但它們的數據傳輸機制卻不同,一個明顯區別是剪貼簿操作幾乎總是用作對用戶指定操作的一次性應答,如從選單中選擇貼上命令。儘管DDE也可以由用戶啟動,但它繼續發揮作用,一般不必用戶進一步干預。
例如:
甲方申請一塊全局記憶體,然後把記憶體指針postmessage到乙方,乙方根據收到的指針訪問那塊全局記憶體。有幾個API函式是做這種事的,你在MSDN里查一下 Dde 打頭的函式全都出來了。因為是已經淘汰的技術,連MFC都沒對他進行封裝。很難保證它同樣會出現在以後的Windows API中。
內容
DDE對話的內容是通過三個標識名來約定的。
1、應用程式名:進行DDE對話的雙方的名稱。商業應用程式的名稱在產品文檔中給出。“組態王”運行系統的程式名是“VIEW”;Microsoft Excel的應用程式名是“Excel”;Visual Basic程式使用的是執行檔的名稱。
2、主題:被討論的數據域(domain)。對“組態王”來說,主題規定為“tagname”;Excel的主題名是電子表格的名稱,比如sheetl,sheet2,……;Visual Basic程式的主題由窗體(Form)的LinkTopic屬性值指定。
3、項目:這是被討論的特定數據對象。在“組態王”的數據詞典里,工程人員定義I/O變數的同時,也定義項目名稱。Excel里的項目是單元,比如rlc2(rlc2表示第一行、第二列的單元)。對Visual Basic程式而言,項目是一個特定的文本框、標籤或圖片框的名稱。
交換方式
(1)冷連線(CoolLink):數據交換是一次性數據傳輸,與剪貼簿相同。當伺服器中的數據發生變化後不通知客戶,但客戶可以隨時從伺服器讀寫數據;
(2)溫連線(WarmLink):當伺服器中的數據發生變化後馬上通知客戶,客戶得到通知後將數據取回;
(3)熱連線(HotLink):當伺服器中的數據發生變化後馬上通知客戶,同時將變化的數據直接送給客戶。
DDE客戶程式向DDE伺服器程式請求數據時,它必須首先知道伺服器的名稱(即DDEService名)、DDE主題名稱(Topics名),還要知道請求哪一個數據項的項目名稱(Items名)。DDEService名應該具有唯一性,否則容易產生混亂。通常DDEService就是伺服器的程式名稱,但不是絕對的,它是由程式設計人員在程式內部設定好的,並不是通過修改程式名稱就可以改變的。Topics名和Items名也是由DDEService在其內部設定好的,所有服務程式的Service名、Topics名都是註冊在系統中,當一個客戶向一個伺服器請求數據時,客戶必須向系統報告伺服器的Service名和Topics名。只有當Service名、Topics名與伺服器內部設定的名稱一致時,系統才將客戶的請求傳達給伺服器。
當服務名和Topics名相符時,伺服器馬上判斷Items名是否合法。如果請求的Item名是伺服器中的合法數據項,伺服器即建立此項連線,建立連線的數據發生數值變化後,伺服器會及時通知客戶。一個伺服器可以有多個Topics名,Items名的數量也不受限制。
DDE交換可以發生在單機或網路中不同計算機的應用程式之間。開發者還可以定義定製的DDE數據格式,進行應用程式之間特別目的IPC,它們有更緊密耦合的通信要求。大多數基於Windows的應用程式都支持DDE。但DDE有個明顯的缺點就是,通信效率低下,當通信量較大時數據刷新速度慢,在數據較少時DDE較實用。
編寫程式
為了使用方便起見,微軟提供DDE管理庫(TheDDEManagementLibrary,簡稱DDEML)。DDEML專門協調DDE通信,給DDE應用程式提供句柄字元串和數據交換的服務,消除了早期由於DDE協定不一致所引起的問題。
使用DDEML開發的應用程式(客戶/伺服器)無論在運行一致性方面,還是在程式相互通信方面,性能均優於沒有使用DDEML的應用程式。而且DDEML的套用使得開發支持DDE的應用程式容易了許多,因為DDEML(這是個DLL)擔起了內務府總管的工作。使用DDEML後,實際上客戶和伺服器之間的多數會話並不是直達對方的,而是經由DDEML中轉,即用Callback函式處理DDE交易(Transaction),而早期的訊息通信是直接的。
在調用其他DDEML函式前,客戶/伺服器必須調用DdeInitialize()函式,以獲取實例標識符,註冊DDECallback函式,並為Callback函式指定事務過濾。對於伺服器,在使用DdeInitialize()初始化後,調用DdeCreateStringHandle()建立Service名、Topics名和Items名等標識的句柄,再通過DdeNameService()在作業系統中註冊伺服器的名字。根據這些句柄,客戶就可以使用它提供的DDE服務了。
為了執行某個DDE任務,許多DDEML函式需要獲得字元串的訪問權。例如:一個客戶在調用DdeConnect()函式來請求同伺服器建立會話時,必須指定Service名和Topics名。可以通過調用DdeCreateStringHandle()函式來獲取特定字元串句柄。例如:
HSZhszServName=DdeCreateStringHandle(idInst,"MyServer",CP_WINANSI);
HSZhszSysTopic=DdeCreateStringHandle(idInst,SZDDESYS_TOPIC,CP_WINANSI);
一個應用程式的DDE回調函式在大多DDE事務中接收多個字元串句柄。比如:在XTYP_REQUEST事務處理期間,一個DDE伺服器接收兩個字元串句柄:一個標識Topics名字元串,另一個標識Items名字元串。可以通過調用DdeQueryString()函式來獲取相應於字元串句柄的字元串長度,並且複製字元串到應用程式定義的buffer中。例如:
DWORDidInst;
DWORDcb;
HSZhszServ;
PSTRpszServName;
cb=DdeQueryString(idInst,hszServ,(LPSTR)NULL,0,CP_WINANSI)+1;
pszServName=(PSTR)LocalAlloc(LPTR,(UINT)cb);
DdeQueryString(idInst,hszServ,pszServName,cb,CP_WINANSI);
根據微軟MSDN,現有的基於訊息DDE協定的應用程式與DDEML應用程式是相容的,也就是說,基於訊息通信的DDE應用程式可以與DDEML應用程式對話和交易。在使用DDEML時,必須在源程式檔案中包括ddeml.h頭檔案,連線user32.lib檔案,並保證ddeml.dll檔案正確的系統路徑。